const RxJs = require('../../library/reactivex/rx');
const record = require('../../service/record');

//队列参数
let list = getApp().list;

//请求队列
const request = (id, options, reactive, requestType) => {

  options.complete = () => {

    list.count--;//进行中的请求数减少

    if (list.wait.length && list.count < 10) {//如果队列中还有请求 并且有空位

      list.count++;//进行中的请求数增加

      const obj = list.wait.splice(0, 1)[0];
      let request;

      if (types.http === requestType) {//出队同时上车
        request = wx.request(obj.options)
      } else if (types.upload === requestType) {
        request = wx.uploadFile(obj.options);
      } else if (types.download === requestType) {
        request = wx.downloadFile(obj.options)
      } else {
        record.err('unkonw request');
      }

      obj.reactive.cancel(() => {
        request.abort();
      });
    }
  };

  if (list.count < 10) {//正在请求的数量少于10 就上车

    list.count++;//进行中的请求数增加
    let request;//上车

    if (types.http === requestType) {
      request = wx.request(options)
    } else if (types.upload === requestType) {
      request = wx.uploadFile(options)
    } else if (types.download === requestType) {
      request = wx.downloadFile(options)
    } else {
      record.err('unkonw request');
    }

    if (request.onProgressUpdate) {
      request.onProgressUpdate((res) => {
        reactive.next(res);
      });
    }

    reactive.cancel(() => {
      request.abort();
    });
  } else {//正在请求的数量大于10

    list.wait.push({ id, options, reactive, requestType });//进队

    reactive.cancel(() => {
      let index = null;
      for (let i of list.wait) {
        if (list.wait[i].id === id) {
          index = i;
          break;
        }
      }
      if (index != null) {
        list.wait.splice(index, 1);
      }
    });
  }
};

const setRequest = (options, requestType) => {

  const id = new Date().getTime() + (list.count + list.wait.length);
  const reactive = RxJs.subject(id);

  options.success = (result) => {
    if (result.statusCode == 200 || result.statusCode == 204) {
      reactive.success(result.data || result.tempFilePath);
      record.log('output from Http 200', options.url, options.data, result);
    } else {
      reactive.fail(result);
      record.err('output from Http ' + result.statusCode, options.url, options.data, result);
    }
  };

  options.fail = (err) => {
    if (err.errMsg.indexOf('abort') === -1) {// for now
      reactive.error(err);
    }

    reactive.fail(err);
    record.err('output from Http InError ' + err.statusCode, options.url, options.data, err);
  };

  request(id, options, reactive, requestType);
  return RxJs.observable(id);
};

const http = (options = {}) => {
  return setRequest(options, types.http);
}

const upload = (options = {}) => {
  return setRequest(options, types.upload);
}

const download = (options = {}) => {
  return setRequest(options, types.download);
}

const types = {
  http: 1,
  upload: 2,
  download: 3
}

module.exports = {
  request: http,
  upload,
  download
}